local function clone(t)
	if type(t) ~= "table" then return t end
	local r = {}
	for k, v in pairs(t) do
		r[k] = clone(v)
	end
	return r
end

local GetBaseDataPoint
do
	local BASE_INFO = {
		-- reverse engineered via playerdb_info
		dodge = {
			WARRIOR = { 0.37, 1.58, 0.72, -17.84, 0.91, }, -- 1.4, 1.7, 32.4, 132.5
			PALADIN = { 0.30, 1.12, 0.47, -8.72, 0.80, }, -- 1.0, 0.6, 24.3, 102.2
			SHAMAN = { 0.25, 4.13, 0.55, -13.62, 1.68, }, -- 0.3, 0.7, 25.1, 83.4
			ROGUE = { 0.25, -1.00, 0.51, -15.77, -0.53, }, -- 0.2, 0.9, 19.8, 109.3
			MAGE = { 0.17, 11.88, 0.21, 10.08, 3.45, }, -- 0.3, 0.7, 25.0, 38.6
			WARLOCK = { 0.27, 4.16, 0.45, -6.58, 2.06, }, -- 0.7, 0.3, 24.7, 72.5
			PRIEST = { 0.19, 9.96, 0.28, 5.36, 3.17, }, -- 0.3, 1.0, 24.9, 45.4
			HUNTER = { 0.34, -0.55, 0.43, -5.02, -5.44, }, -- 0.3, 0.7, 25.0, 260.8
			DRUID = { 0.16, 1.82, 0.25, -2.95, -1.91, }, -- 0.2, 0.5, 14.4, 99.5
		},
		crit = {
			WARRIOR = { 0.29, 1.77, 1.30, -58.15, 1.14, }, -- 0.2, 0.7, 33.0, 127.5
			PALADIN = { 0.27, 2.46, 0.54, -12.69, 0.66, }, -- 0.2, 0.8, 25.1, 108.9
			SHAMAN = { 0.24, 4.21, 0.55, -13.29, 1.67, }, -- 0.2, 0.7, 25.1, 83.4
			ROGUE = { 0.49, -2.04, 1.17, -41.64, -0.29, }, -- 0.2, 1.2, 40.5, 214.3
			MAGE = { 0.17, 11.98, 0.21, 10.08, 3.46, }, -- 0.3, 0.7, 25.0, 38.5
			WARLOCK = { 0.24, 4.80, 0.46, -7.57, 2.00, }, -- 0.2, 0.7, 24.6, 73.8
			PRIEST = { 0.19, 9.76, 0.28, 5.36, 3.18, }, -- 0.2, 0.7, 24.9, 45.2
			HUNTER = { 0.56, -1.28, 0.69, -8.46, -1.53, }, -- 0.3, 0.8, 40.0, 261.4
			DRUID = { 0.27, 3.06, 0.47, -7.79, 0.96, }, -- 0.2, 0.9, 25.1, 101.5
		},
		spellcrit = {
			WARRIOR = { 0, 0, 0, 0, -1.00, },
			PALADIN = { 0.76, 6.18, 2.20, -72.21, 3.33, }, -- 0.8, 7.6, 81.5, 135.7
			SHAMAN = { 0.93, -0.30, 2.23, -75.21, 2.20, }, -- 0.5, 3.0, 80.9, 226.6
			ROGUE = { 0, 0, 0, 0, -1.00, },
			MAGE = { 1.20, -4.43, 1.03, 5.78, 0.91, }, -- 0.8, 0.1, 78.1, 319.6
			WARLOCK = { 1.02, -2.09, 2.17, -69.16, 1.70, }, -- 0.6, 1.6, 82.6, 272.4
			PRIEST = { 1.15, -4.03, 1.38, -16.78, 1.24, }, -- 0.5, 1.0, 79.9, 300.2
			HUNTER = { 0.87, 7.32, 1.92, -53.80, 3.60, }, -- 0.7, 2.1, 80.6, 112.4
			DRUID = { 1.01, -1.23, 2.00, -59.81, 1.85, }, -- 0.5, 1.1, 80.4, 253.1
		}
	}

	GetBaseDataPoint = function(type, unit, value)
		local info = BASE_INFO[type]
		local numbers = info[unit.class]
		local level = unit.level
		local a, b
		if level < 60 then
			a, b = numbers[1], numbers[2]
		else
			a, b = numbers[3], numbers[4]
		end
		local m = a * level + b
		return (m == 0) and 0 or (value / m + numbers[5])
	end
end

local EMPTY_TIER1 = {
	agility = 0,
	intellect = 0,
	spirit = 0,
	stamina = 0,
	strength = 0,
	
	health = 0,
	mana = 0,
	armor = 0,
	
	dodge = 0,
	parry = 0,
	block = 0,
	
	blockvalue = 0,
	
	meleehit = 0,
	meleecrit = 0,
	meleehaste = 0,
	meleehit_taken = 0,
	meleecrit_taken = 0,
	meleeattackpower = 0,
	
	rangedhit = 0,
	rangedcrit = 0,
	rangedhaste = 0,
	rangedhit_taken = 0,
	rangedcrit_taken = 0,
	rangedattackpower = 0,
	
	spellhit = 0,
	spellcrit = 0,
	spellhaste = 0,
	spellhit_taken = 0,
	spellcrit_taken = 0,
	
	healing = 0,
	spelldamage = 0,
	
	manareg = 0,
	healthreg = 0,
	
	healthreg_fight = 0,
	manareg_fsr_p = 0,
	manareg_fsr = 0,
	
	skill_defense = 0,
	
	skill_weapon_dagger = 0,
	skill_weapon_sword = 0,
	skill_weapon_sword_2h = 0,
	skill_weapon_axe = 0,
	skill_weapon_axe_2h = 0,
	skill_weapon_mace = 0,
	skill_weapon_mace_2h = 0,
	skill_weapon_bow = 0,
	skill_weapon_crossbow = 0,
	skill_weapon_gun = 0,
	skill_weapon_fist = 0,
	skill_weapon_staff = 0,
	skill_weapon_polearm = 0,
	skill_weapon_feral = 0,
	
	expertise = 0,
	resilience = 0,

	ratings = {},
	
	modifiers = {},
	ref_modifiers = {},
}

local GetRatingBonus
do 
	local RATINGS = {
		skill_weapon_dagger = 2.5,
		skill_weapon_sword = 2.5,
		skill_weapon_sword_2h = 2.5,
		skill_weapon_axe = 2.5,
		skill_weapon_axe_2h = 2.5,
		skill_weapon_mace = 2.5,
		skill_weapon_mace_2h = 2.5,
		skill_weapon_bow = 2.5,
		skill_weapon_crossbow = 2.5,
		skill_weapon_gun = 2.5,
		skill_weapon_fist = 2.5,
		skill_weapon_staff = 2.5,
		skill_weapon_polearm = 2.5,

		skill_defense = 1.5,
		
		dodge = 12,
		parry = 15,
		block = 5,
		
		meleehit = 10,
		meleecrit = 14,
		meleehaste = 10,
		meleehit_taken = 10,
		
		rangedhit = 10,
		rangedcrit = 14,
		rangedhaste = 10,
		rangedhit_taken = 10,
		
		spellhit = 8,
		spellcrit = 14,
		spellhaste = 10,
		spellhit_taken = 8,
		
		resilience = 25,
		expertise = 2.5,
	}
	GetRatingBonus = function (type, rating, level)
		local mult
		if level < 10 then
			mult = 26
		elseif level <= 60 then
			mult = 52 / (level - 8)
		elseif level <= 70 then
			mult = 3.1951219512195124 - 0.036585365853658534 * level
		end
		return rating * mult / RATINGS[type]
	end
end

local function calc_tier1_values(unit)
	local tier1 = {}
	for stat, value in pairs(EMPTY_TIER1) do
		if type(value) == "table" then
			tier1[stat] = {}
		else
			tier1[stat] = value
		end
	end
	for stat, value in pairs(unit.innate) do
		if type(value) == "number" then
			tier1[stat] = value
		end
	end
	for _, aura in ipairs(unit.auras) do
		if aura.type == "stat" then
			local stat = aura.attribute
			tier1[stat] = (tier1[stat] or 0) + aura.value
		elseif aura.type == "rating" then
			local stat = aura.attribute
			tier1.ratings[stat] = (tier1.ratings[stat] or 0) + aura.value
		elseif aura.type == "modifier" then
			local stat = aura.attribute
			if not aura.reference then
				tier1.modifiers[stat] = (tier1.modifiers[stat] or 0) + aura.value
			else
				local t = tier1.ref_modifiers[stat]
				if not t then
					t = {}
					tier1.ref_modifiers[stat] = t
				end
				t[#t + 1] = { reference = aura.reference, modifier = aura.modifier }
			end
		end
	end
	return tier1
end

local get_tier2_value
local function apply_modifier(unit, tier1, type, value)
	local modifier = tier1.modifiers[type]
	if modifier and modifier ~= 0 then
		value = value * (1 + modifier / 100)
	end
	local rmods = tier1.ref_modifiers[type]
	if rmods then
		for _, mod in ipairs(rmods) do
			value = value + get_tier2_value(unit, tier1, mod.reference) * mod.modifier
		end
	end
	return value
end

local function default_get_tier2_value(unit, tier1, type)
	local value = tier1[type] or 0
	if value ~= 0 then
		value = apply_modifier(unit, tier1, type, value)
	end
	local rating = tier1.ratings[type]
	if rating and rating ~= 0 then
		value = (value or 0) + GetRatingBonus(type, rating, unit.level)
	end
	return value or 0
end

local function get_tier2_defense_bonus(unit, tier1)
	return default_get_tier2_value(unit, tier1, "skill_defense") - unit.level * 5
end

local function get_tier2_dodge(unit, tier1)
	local value = default_get_tier2_value(unit, tier1, "dodge")
	local agility = default_get_tier2_value(unit, tier1, "agility")
	
	value = value + GetBaseDataPoint("dodge", unit, agility)
	
	local def_bonus = get_tier2_defense_bonus(unit, tier1)
	if def_bonus > 0 then
		value = value + def_bonus * 0.04
	end
	
	return value
end

local function get_tier2_parry(unit, tier1)
	if not unit.can_parry then return 0 end
	local value = default_get_tier2_value(unit, tier1, "parry")

	local def_bonus = get_tier2_defense_bonus(unit, tier1)
	if def_bonus > 0 then
		value = value + def_bonus * 0.04
	end
	
	return value
end

local function get_tier2_block(unit, tier1)
	if not unit.can_block then return 0 end
	local value = default_get_tier2_value(unit, tier1, "block")

	local def_bonus = get_tier2_defense_bonus(unit, tier1)
	if def_bonus > 0 then
		value = value + def_bonus * 0.04
	end
	
	return value
end

local function get_tier2_blockvalue(unit, tier1)
	if not unit.can_block then return 0 end
	local value = default_get_tier2_value(unit, tier1, "blockvalue")

	local strength = default_get_tier2_value(unit, tier1, "strength")
	
	return value + strength / 20
end

local function get_tier2_meleecrit(unit, tier1)
	local value = default_get_tier2_value(unit, tier1, "meleecrit")
	local agility = default_get_tier2_value(unit, tier1, "agility")
	
	value = value + GetBaseDataPoint("crit", unit, agility)
	
	return value
end

local function get_tier2_rangedcrit(unit, tier1)
	local value = default_get_tier2_value(unit, tier1, "rangedcrit")
	local agility = default_get_tier2_value(unit, tier1, "agility")
	
	value = value + GetBaseDataPoint("crit", unit, agility)
	
	return value
end

local function get_tier2_health(unit, tier1)
	local stamina = default_get_tier2_value(unit, tier1, "stamina")
	local value = tier1.health + (stamina * 10 - 180)
	value = apply_modifier(unit, tier1, "health", value)
	
	return value
end

local function get_tier2_mana(unit, tier1)
	local intellect = default_get_tier2_value(unit, tier1, "intellect")
	local value = tier1.mana + (intellect * 15 - 280)
	value = apply_modifier(unit, tier1, "mana", value)
	
	return value
end

local function get_tier2_armor(unit, tier1)
	local agility = default_get_tier2_value(unit, tier1, "agility")
	local value = tier1.armor + agility * 2
	return default_get_tier2_value(unit, tier1, "base_armor") 
		+ apply_modifier(unit, tier1, "armor", value)
end

local function get_tier2_spellcrit(unit, tier1)
	local value = default_get_tier2_value(unit, tier1, "spellcrit")
	local intellect = default_get_tier2_value(unit, tier1, "intellect")
	
	value = value + GetBaseDataPoint("spellcrit", unit, intellect)
	
	return value
end

local AP_MULT = {
	melee = {
		WARRIOR = { 0, 2, },
		PALADIN = { 0, 2, },
		SHAMAN = { 0, 2, },
		ROGUE = { 1, 1, },
		MAGE = { 0, 2, },
		WARLOCK = { 0, 2, },
		PRIEST = { 0, 2, },
		HUNTER = { 1, 1, },
		DRUID = { 0, 2, },
	},
	ranged = {
		WARRIOR = { 0, 0, },
		PALADIN = { 0, 0, },
		SHAMAN = { 0, 0, },
		ROGUE = { 0, 0, },
		MAGE = { 0, 0, },
		WARLOCK = { 0, 0, },
		PRIEST = { 0, 0, },
		HUNTER = { 1, 0, },
		DRUID = { 0, 0, },
	},
}

local function get_tier2_meleeattackpower(unit, tier1)
	local agility = default_get_tier2_value(unit, tier1, "agility")
	local strength = default_get_tier2_value(unit, tier1, "strength")
	local value = tier1.meleeattackpower + agility * AP_MULT.melee[unit.class][1] + strength * AP_MULT.melee[unit.class][2]
	value = apply_modifier(unit, tier1, "meleeattackpower", value)
	
	return value
end

local function get_tier2_rangedattackpower(unit, tier1)
	local agility = default_get_tier2_value(unit, tier1, "agility")
	local strength = default_get_tier2_value(unit, tier1, "strength")
	local value = tier1.rangedattackpower + agility * AP_MULT.ranged[unit.class][1] + strength * AP_MULT.ranged[unit.class][2]
	value = apply_modifier(unit, tier1, "rangedattackpower", value)
	
	return value
end

local SPI_MANAREG = {
	PALADIN = { 5, 15 },
	SHAMAN = { 5, 15 },
	MAGE = { 4, 12.5 },
	WARLOCK = { 5, 15 },
	PRIEST = { 4, 12.5 },
	HUNTER = { 5, 15 },
	DRUID = { 4.5, 15 },
}

local function get_spirit_manareg(class, spirit)
	local data = SPI_MANAREG[class]
	if not data then return end
	local value = spirit / data[1] + data[2]
	value = value / 2 * 5 -- convert ticks to MP5
	return value
end

local function get_tier2_manareg(unit, tier1)
	-- mana regen when not in FSR.
	local spreg = get_spirit_manareg(unit.class, default_get_tier2_value(unit, tier1, "spirit"))
	if not spreg then return end
		
	return default_get_tier2_value(unit, tier1, "manareg_fsr") + spreg
end

local function get_tier2_manareg_fsr(unit, tier1)
	local spreg = get_spirit_manareg(unit.class, default_get_tier2_value(unit, tier1, "spirit"))
	if not spreg then return end
	local value = default_get_tier2_value(unit, tier1, "manareg_fsr")
	local p = default_get_tier2_value(unit, tier1, "manareg_fsr_p")
	
	value = value + spreg * p
	
	return value
end

local TIER2_CALCULATORS = {
	health = get_tier2_health,
	mana = get_tier2_mana,
	armor = get_tier2_armor,
	base_armor = function () return end,
	
	dodge = get_tier2_dodge,
	parry = get_tier2_parry,
	block = get_tier2_block,
	
	blockvalue = get_tier2_blockvalue,
	
	meleecrit = get_tier2_meleecrit,
	meleeattackpower = get_tier2_meleeattackpower,
	
	rangedcrit = get_tier2_rangedcrit,
	rangedattackpower = get_tier2_rangedattackpower,
	
	spellcrit = get_tier2_spellcrit,
	
	manareg = get_tier2_manareg,
	manareg_fsr = get_tier2_manareg_fsr,
	manareg_fsr_p = function () return end,
}

function get_tier2_value(unit, tier1, stat)
	if type(tier1[stat]) == "number" then
		local calculator = TIER2_CALCULATORS[stat] or default_get_tier2_value
		return calculator(unit, tier1, stat)
	end
end

local function calc_tier2_values(unit)
	local tier1 = calc_tier1_values(unit)
	local tier2 = {}
	for stat, v in pairs(tier1) do
		tier2[stat] = get_tier2_value(unit, tier1, stat)
	end
	return tier2
end

local equipment = {
	head = {
		stat = {
			armor = 237,
			agility = 25,
			stamina = 21,
			attackpower = 66,
			cr_hit = 14,
		},
		enchant = {
			attackpower = 34,
			cr_hit = 16,
		},
		socket1 = {
			cr_crit = 4,
		},
		socket2 = {
			attackpower = 20,
		},
		socket_bonus = {
			cr_resilience = 4,
		},
	},
	neck = {
		stat = {
			stamina = 27,
			cr_skill_defense = 19,
			cr_dodge = 18,
		},
	},
	shoulders = {
		stat = {
			armor = 188,
			agility = 11,
			stamina = 16,
			attackpower = 56,
			cr_hit = 10,
		},
		enchant = {
			attackpower = 26,
		},
	},
	back = {
		stat = {
			armor = 385,
			stamina = 30,
			cr_skill_defense = 24,
		},
		enchant = {
			armor = 120,
		},
	},
	chest = {
		stat = {
			armor = 378,
			strength = 36,
			agility = 34,
			stamina = 24,
		},
		enchant = {
			stamina = 8,
		},
	},
	wrists = {
		stat = {
			armor = 281,
			strength = 20,
			agility = 10,
			stamina = 22,
		},
	},
	mainhand = {
		stat = {
			armor = 500,
			stamina = 75,
			cr_dodge = 54,
			-- attackpower = 773,
		},
	},
	hands = {
		stat = {
			armor = 228,
			agility = 35,
			stamina = 22,
			attackpower = 42,
		},
		socket1 = {
			agility = 4,
		},
		socket2 = {
			stamina = 6,
		},
		socket_bonus = {
			cr_crit = 3,
		},
	},
	waist = {
		stat = {
			armor = 205,
			agility = 18,
			stamina = 37,
			attackpower = 58,
		},
		socket1 = {
			cr_hit = 3,
			agility = 3,
		},
		socket2 = {
			cr_hit = 3,
			agility = 3,
		},
		socket_bonus = {
			agility = 3,
		},
	},
	legs = {
		stat = {
			armor = 256,
			agility = 40,
			stamina = 33,
			cr_hit = 22,
			attackpower = 44,
		},
		enchant = {
			stamina = 30,
			agility = 10,
		},
	},
	feet = {
		stat = {
			armor = 390,
			strength = 34,
			agility = 28,
			stamina = 33,
		},
	},
	finger1 = {
		stat = {
			armor = 294,
			stamina = 31,
			cr_skill_defense = 22,
		},
	},
	finger2 = {
		stat = {
			agility = 18,
			stamina = 27,
			attackpower = 38,
		},
	},
	trinket2 = {
		stat = {
			attackpower = 52,
		},
	},
}

local heal_eq = {
	head = {
		stat = {
			armor = 321,
			stamina = 34,
			intellect = 42,
			spirit = 34,
			healing = 92,
		},
		enchant = {
			healing = 35,
			manareg = 7,
		},
	},
	neck = {
		stat = {
			stamina = 18,
			intellect = 21,
			spirit = 19,
			healing = 46,
		},
	},
	shoulders = {
		stat = {
			armor = 284,
			stamina = 19,
			intellect = 23,
			spirit = 19,
			healing = 68,
			manareg = 5,
		},
		socket1 = {
			healing = 9,
			spirit = 4,
		},
		socket2 = {
			healing = 9,
			spirit = 4,
		},
		socket_bonus = {
			spirit = 3,
		},
		enchant = {
			healing = 29,
		},
	},
	back = {
		stat = {
			armor = 105,
			stamina = 22,
			intellect = 23,
			healing = 53,
			manareg = 7,
		},
	},
	chest = {
		stat = {
			armor = 404,
			stamina = 48,
			intellect = 32,
			spirit = 34,
			healing = 110,
		},
		enchant = {
			spirit = 15,
		},
	},
	wrists = {
		stat = {
			armor = 177,
			stamina = 21,
			intellect = 14,
			spirit = 21,
			healing = 68,
		},
		enchant = {
			healing = 30,
		},
	},
	mainhand = {
		stat = {
			stamina = 33,
			intellect = 34,
			spirit = 55,
			healing = 348,
		},
		enchant = {
			spirit = 20,
		},
	},
	hands = {
		stat = {
			armor = 237,
			stamina = 22,
			intellect = 25,
			spirit = 24,
			healing = 62,
			manareg = 7,
		},
		enchant = {
			healing = 35,
		},
	},
	waist = {
		stat = {
			armor = 227,
			stamina = 22,
			intellect = 23,
			spirit = 24,
			healing = 73,
		},
		socket1 = {
			healing = 11,
			stamina = 6,
		},
		socket2 = {
			healing = 11,
			stamina = 6,
		},
		socket_bonus = {
			healing = 7,
		},
	},
	legs = {
		stat = {
			armor = 367,
			stamina = 37,
			intellect = 36,
			spirit = 27,
			healing = 101,
			manareg = 11,
		},
		socket1 = {
			healing = 9,
			spirit = 4,
		},
		socket_bonus = {
			healing = 4,
		},
		enchant = {
			healing = 66,
			stamina = 20,
		},
	},
	feet = {
		stat = {
			armor = 250,
			stamina = 24,
			intellect = 27,
			spirit = 16,
			healing = 55,
		},
		socket1 = {
			healing = 9,
			manareg = 2,
		},
		socket2 = {
			healing = 11,
			manareg = 2,
		},
		socket_bonus = {
			healing = 7,
		},
		enchant = {
			spirit = 5,
		},
	},
	finger1 = {
		stat = {
			intellect = 12,
			spirit = 11,
			healing = 59,
		},
	},
	finger2 = {
		stat = {
			stamina = 24,
			intellect = 23,
			spirit = 17,
			healing = 55,
		},
	},
	trinket1 = {
		stat = {
			healing = 66,
			manareg = 9,
		},
	},
	trinket2 = {
		stat = {
			healing = 73,
		},
	},
}

local heal2_eq = {
	head = {
		stat = { -- ZA
			armor = 328,
			stamina = 33,
			intellect = 39,
			spirit = 30,
			healing = 86,
		},
		enchant = {
			healing = 35,
			manareg = 7,
		},
		socket1 = {
			healing = 9,
			spirit = 4,
		},
		socket2 = {
			healing = 9,
			spirit = 4,
		},
		socket3 = {
			healing = 9,
			intellect = 4,
		},
		socket_bonus = {
			healing = 9,
		},
	},
	neck = { -- Netherspite
		stat = {
			stamina = 18,
			intellect = 21,
			spirit = 19,
			healing = 46,
		},
	},
	shoulders = { -- Vashj
		stat = {
			armor = 326,
			stamina = 31,
			intellect = 22,
			spirit = 32,
			healing = 101,
		},
		enchant = {
			healing = 29,
		},
	},
	back = { -- Kael'Thas
		stat = {
			armor = 116,
			stamina = 18,
			intellect = 24,
			spirit = 20,
			healing = 77,
		},
	},
	chest = { -- Morogrim
		stat = {
			armor = 404,
			stamina = 48,
			intellect = 32,
			spirit = 34,
			healing = 110,
		},
		enchant = {
			spirit = 15,
		},
	},
	wrists = { -- Lurker
		stat = {
			armor = 177,
			stamina = 21,
			intellect = 14,
			spirit = 21,
			healing = 68,
		},
		enchant = {
			healing = 30,
		},
	},
	mainhand = { -- Solarian
		stat = {
			stamina = 52,
			intellect = 44,
			spirit = 62,
			healing = 415,
		},
		enchant = {
			spirit = 20,
		},
	},
	hands = { -- trash TK
		stat = {
			armor = 252,
			stamina = 28,
			intellect = 25,
			spirit = 33,
			healing = 73,
		},
		enchant = {
			healing = 35,
		},
	},
	waist = { -- void reaver
		stat = {
			armor = 227,
			stamina = 22,
			intellect = 23,
			spirit = 24,
			healing = 73,
		},
		socket1 = {
			healing = 11,
			stamina = 6,
		},
		socket2 = {
			healing = 11,
			stamina = 6,
		},
		socket_bonus = {
			healing = 7,
		},
	},
	legs = { -- T5
		stat = {
			armor = 367,
			stamina = 37,
			intellect = 36,
			spirit = 27,
			healing = 101,
			manareg = 11,
		},
		socket1 = {
			healing = 9,
			spirit = 4,
		},
		socket_bonus = {
			healing = 4,
		},
		enchant = {
			healing = 66,
			stamina = 20,
		},
	},
	feet = { -- Leotheras
		stat = {
			armor = 278,
			stamina = 19,
			intellect = 27,
			spirit = 19,
			healing = 73,
		},
		socket1 = {
			healing = 9,
			spirit = 4,
		},
		socket2 = {
			healing = 9,
			spirit = 4,
		},
		socket_bonus = {
			spirit = 3,
		},
		enchant = {
			spirit = 5,
		},
	},
	finger1 = { -- Vashj
		stat = {
			stamina = 21,
			intellect = 14,
			spirit = 27,
			healing = 75,
		},
	},
	finger2 = { -- rep Karazhan
		stat = {
			stamina = 24,
			intellect = 23,
			spirit = 17,
			healing = 55,
		},
	},
	trinket1 = {
		stat = {
			healing = 66,
			manareg = 9,
		},
	},
	trinket2 = {
		stat = {
			healing = 73,
		},
	},
}

local buffs = {
	mark_of_the_wild = {
		buff = {
			armor = math.floor(340*1.35),
			agility = math.floor(14*1.35),
			intellect = math.floor(14*1.35),
			spirit = math.floor(14*1.35),
			stamina = math.floor(14*1.35),
			strength = math.floor(14*1.35),
		},
	},
	fortitude = {
		buff = {
			stamina = math.floor(79*1.3),
		},
	},
	well_fed = {
		buff = {
--~ 			stamina = 20,
			healing = 44,
			spirit = 20,
		},
	},
	arcane_brilliance = {
		buff = {
			intellect = 40,
		},
	},
	spirit = {
		buff = {
			spirit = 50,
		},
		auras = {
			{ type = "modifier", attribute = "healing", reference = "spirit", modifier = 0.1 },
		},
	},
--~ 	blood_pact = {
--~ 		buff = {
--~ 			stamina = math.floor(66*1.3),
--~ 		},
--~ 	},
	wisdon_elixir = {
		buff = {
			intellect = 30,
			spirit = 30,
		},
	},
	blessing_kings = {
		auras = {
			{ type = "modifier", attribute = "agility", value = 10 },
			{ type = "modifier", attribute = "intellect", value = 10 },
			{ type = "modifier", attribute = "spirit", value = 10 },
			{ type = "modifier", attribute = "stamina", value = 10 },
			{ type = "modifier", attribute = "strength", value = 10 },
		},
	},
}

local function insert_auras(unit, stuff)
	for slot, item in pairs(stuff) do
		for type, stats in pairs(item) do
			if type == "auras" then
				for _, aura in ipairs(stats) do
					unit.auras[#unit.auras + 1] = aura
				end
			else
				for stat, value in pairs(stats) do
					local rating
					if stat:sub(1, 3) == "cr_" then
						rating = true
						stat = stat:sub(4)
					end
					local rstat
					if stat == "hit" or stat == "crit" or stat == "haste" or stat == "attackpower" then
						rstat = "ranged"..stat
						stat = "melee"..stat
					elseif stat == "armor" and type == "stat" then
						stat = "base_armor"
					elseif stat == "manareg" then
						stat = "manareg_fsr"
					end
					unit.auras[#unit.auras + 1] = { type = rating and "rating" or "stat", attribute = stat, value = value }
					if rstat then
						unit.auras[#unit.auras + 1] = { type = rating and "rating" or "stat", attribute = rstat, value = value }
					end
				end
			end
		end
	end
end


local unit = {
	class = "DRUID",
	level = 70,
	innate = {
		strength = 73,
		intellect = 120,
		agility = 75, 
		stamina = 82, 
		spirit = 132,
		skill_defense = 350,
		skill_weapon_feral = 350,
		armor = 0,
		health = 3614,
		mana = 2370,
		meleeattackpower = -20,
	},
	auras = {
		-- Talents
		{ type = "modifier", attribute = "spirit", value = 15 }, 
		{ type = "stat", attribute = "spellcrit", value = 3 },
--		{ type = "stat", attribute = "manareg_fsr_p", value = 0.15 },
		{ type = "stat", attribute = "manareg_fsr_p", value = 0.30 }, -- 2.3
		-- Night Elf
		{ type = "stat", attribute = "dodge", value = 1 },
		-- Dire Bear form:
--~ 		{ type = "modifier", attribute = "base_armor", value = 400 },
--~ 		{ type = "modifier", attribute = "stamina", value = 25 },
--~ 		{ type = "stat", attribute = "meleeattackpower", value = 120 },
	},
}

local unit_23 = clone(unit)
unit_23.auras[3].value = 0.3

--~ insert_auras(unit, equipment)
insert_auras(unit, heal_eq)
insert_auras(unit, buffs)

insert_auras(unit_23, heal2_eq)
insert_auras(unit_23, buffs)

TIER2_CALCULATORS.innervate = function (unit, t1)
	local manareg = get_tier2_value(unit, t1, "manareg")
	return manareg * (1 + 400 / 100) * (2 / 5) * (18 / 2)
end
EMPTY_TIER1.innervate = 0

TIER2_CALCULATORS.regrowth_healing_power = function (unit, t1)
	local healing = get_tier2_value(unit, t1, "healing") + 0.25 * get_tier2_value(unit, t1, "spirit")
	local mana = get_tier2_value(unit, t1, "mana") + get_tier2_value(unit, t1, "innervate")
	local FSR_RATIO = 0.8
	local manareg = (get_tier2_value(unit, t1, "manareg_fsr") * FSR_RATIO + get_tier2_value(unit, t1, "manareg") * (1 - FSR_RATIO)) / 5
	
	local regrowth_healing = (healing * 0.499 + (1215 + 1355) / 2)
	local regrowth_time = 2
	local regrowth_cost = 845 * 0.8 - manareg * regrowth_time
	
	local regrowth_casts = mana / regrowth_cost
	local regrowth_heal = regrowth_healing * regrowth_casts

	local crit = get_tier2_value(unit, t1, "spellcrit") / 100 + 0.5
	crit = 1 + (crit / 100)
	
	return regrowth_heal * crit
end
EMPTY_TIER1.regrowth_healing_power = 0

TIER2_CALCULATORS.lifebloom_healing_power = function (unit, t1)
	local healing = get_tier2_value(unit, t1, "healing") + 0.25 * get_tier2_value(unit, t1, "spirit")
	local mana = get_tier2_value(unit, t1, "mana") + get_tier2_value(unit, t1, "innervate")
	local FSR_RATIO = 0.8
	local manareg = (get_tier2_value(unit, t1, "manareg_fsr") * FSR_RATIO + get_tier2_value(unit, t1, "manareg") * (1 - FSR_RATIO)) / 5
	
	local crit = get_tier2_value(unit, t1, "spellcrit") / 100
	crit = 1 + (crit / 100)
	local lifebloom_healing = ((healing * 0.46 + 273) + (healing * 0.46 + 600)) * crit
	local lifebloom_time = 1.5
	local lifebloom_cost = 220 * 0.8 - manareg * lifebloom_time
	
	local lifebloom_casts = mana / lifebloom_cost
	local lifebloom_heal = lifebloom_healing * lifebloom_casts
	
	return lifebloom_heal
end
EMPTY_TIER1.lifebloom_healing_power = 0

local v1, v2 = calc_tier2_values(unit), calc_tier2_values(unit_23)

for s, v in pairs(v1) do
	if v ~= 0 or v2[s] ~= 0 then
		local diff = v2[s] - v
		if diff > 0 then
			diff = ("+%.1f"):format(diff)
		elseif diff < 0 then
			diff = ("-%.1f"):format(-diff)
		else
			diff = ""
		end
		print(s, v2[s], diff)
	end
end
